package cate.game.fight.hero;

import cate.common.table.d.GDPos;
import cate.common.table.dynins.DynHeroLevelRow;
import cate.common.table.fight.skill.row.SkillBaseRow;
import cate.common.table.ins.InstanceHeroRow;
import cate.common.table.item.hero.row.HeroBaseRow;
import cate.game.attr.FightAttr;
import cate.game.attr.PowerAttrPart;
import cate.game.attr.PowerManager;
import cate.game.fight.hero.dyn.DynHeroUtil;
import cate.game.play.part.BattleHero;
import cate.game.play.support.PlayBuildContext;
import cate.game.play.support.PlayBuildContextWith;
import cate.game.play.vo.HeroVO;
import cate.game.power.PowerFactor;
import cate.game.role.Role;
import cate.game.role.bag.hero.Hero;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@NoteClass("战斗英雄构建builderr")
public class BattleHeroBuilder extends PlayBuildContextWith {

	@NoteField("动态实例英雄构建handler")
	private DynHeroUtil dynIns = new DynHeroUtil();


	@Override
	public void init(PlayBuildContext ctx) throws Exception {
		super.init(ctx);
		dynIns.init(ctx);
	}

	/**
	 * 不考虑主角和布阵的因素
	 * @param hero
	 * @return
	 */
	public BattleHero buildPure(Hero hero) {
		return buildExe(null, hero,GDPos.P_NULL);
	}

	/**
	 * 只考虑主角培养信息  不考虑布阵
	 * @param role
	 * @param hero
	 * @return
	 */
	public BattleHero buildInBag(Role role, Hero hero) {
		return buildExe(new PowerFactor(role), hero, GDPos.P_NULL);
	}

	/**
	 * 考虑各类外部加成信息
	 * @param powerFactor
	 * @param hero
	 * @return
	 */
	public BattleHero buildInPosition(PowerFactor powerFactor, Hero hero, byte pos) {
		return buildExe(powerFactor, hero, pos);
	}

	/**
	 *
	 * @param powerFactor 外部战力因素
	 * @param hero 英雄
	 * @param pos 位置
	 * @return
	 */
	private BattleHero buildExe(PowerFactor powerFactor, Hero hero, byte pos) {
		BattleHero battleHero = new BattleHero();
		battleHero.hero = new HeroVO().read(hero);
		//各类系统提供的属性 技能 附加战力
		PowerAttrPart allPart = new PowerAttrPart();
		//英雄身上的装备符文等
		allPart.merge(hero.getPowerAttrPart(ctx));
		//外部战力因素 （如阵法 仙盟培养 图腾等）
		if (powerFactor != null) {
			allPart.merge(powerFactor.buildHeroPart(ctx, hero, pos));
		}
		//所有技能汇总

		//自身技能
		List<Integer> skillIds = new ArrayList<>(hero.getSelfSkills(ctx));
		//外部提供技能
		skillIds.addAll(allPart.skills);
		skillIds = filterSkill(skillIds);
		battleHero.setSkills(skillIds);
		//技能提供的属性
		allPart.merge(buildSkillAttrPart(skillIds));

		//总属性
		FightAttr total = new FightAttr();
		//英雄基础属性 （升星 升级 升阶）
		FightAttr base = hero.getSelfAttr(ctx);
		//汇总所有属性
		total.add(base).add(allPart.attr);
		battleHero.setAttr(total);
		//计算战力
		battleHero.power = PowerManager.calcByAttr(total, ctx) + allPart.powerExt;

		//pvp属性和技能
		battleHero.setPvpAttr(allPart.pvpAttr);
		battleHero.setPvpSkills(allPart.pvpSkills);
		return battleHero;
	}

	/**
	 * 根据静态实例构建英雄
	 * @param row
	 * @return
	 */
	public BattleHero buildByInsRow(InstanceHeroRow row) {
		if (ctx.heroExcel().base.get(row.heroTid) == null) {
			return null;
		}
		Hero hero = new Hero(null, row.heroTid);
		hero.level = row.level;
		hero.grade = row.grade;
		BattleHero battleHero = buildPure(hero);
		if (StringUtils.isNotBlank(row.rewriteAttrCode)) {
			battleHero.setAttr(new FightAttr(row.rewriteAttrCode));
		}
		if (StringUtils.isNotBlank(row.exAttrCode)) {
			battleHero.addAttr(new FightAttr(row.exAttrCode));
		}
		if (row.rewriteSkills != null) {
			battleHero.setSkills(row.rewriteSkills);
		}
		if (row.exSkills != null) {
			battleHero.addSkills(row.exSkills);
		}
		return battleHero;
	}

	/**
	 * 根据动态实例配置构建英雄
	 * @param heroTid
	 * @param level
	 * @return
	 */
	public BattleHero buildByDynCfg(PowerFactor powerFactor, int heroTid, int level) {
		Hero hero = buildDynHero(heroTid, level);
		if (hero == null) {
			return null;
		}
		setUpHeroItem(hero);
		return buildExe(powerFactor, hero, GDPos.P_NULL);
	}

	private Hero buildDynHero(int heroTid, int level) {
		Hero hero = new Hero(null, heroTid);
		HeroBaseRow tpl = hero.getTpl(ctx);
		if (tpl == null) {
			return null;
		}
		hero.initialize(null);
		hero.level = level;
		hero.grade = ctx.dynInsExcel().heroGrade.getOffSet(level);
		return hero;
	}



	/**
	 * 根据英雄的等级动态构建装备
	 * @param hero
	 */
	public void setUpHeroItem(Hero hero) {
		if (hero == null) {
			return;
		}
		HeroBaseRow heroTpl = hero.getTpl(ctx);
		if (heroTpl == null) {
			return;
		}
		DynHeroLevelRow itemTpl = ctx.dynInsExcel().heroLevel.get(hero.level);
		if (itemTpl == null) {
			return;
		}
		dynIns.setUp(hero,heroTpl, itemTpl);
	}


	/**
	 * 过滤技能
	 * @param skrList
	 * @return
	 */
	public List<Integer> filterSkill(List<Integer> skrList) {
		Map<Integer, SkillBaseRow> noRepeatSkr = new HashMap<>();
		for (Integer skr : skrList) {
			SkillBaseRow skillRow = ctx.skillExcel().base.get(skr);
			if (skillRow == null) {
				continue;
			}
			SkillBaseRow before = noRepeatSkr.get(skillRow.protoId);
			if (before == null) {
				noRepeatSkr.put(skillRow.protoId, skillRow);
			} else {
				if (skillRow.level > before.level) {
					noRepeatSkr.put(skillRow.protoId, skillRow);
				}
			}
		}
		return noRepeatSkr.values().stream().mapToInt(a -> a.tid).boxed().collect(Collectors.toList());
	}

	/**
	 * 技能提供的属性加成
	 * @param skills
	 * @return
	 */
	public PowerAttrPart buildSkillAttrPart(List<Integer> skills) {
		PowerAttrPart part = new PowerAttrPart();
		for (Integer skill : skills) {
			SkillBaseRow skillRow = ctx.skillExcel().base.get(skill);
			if (skillRow != null) {
				if (StringUtils.isNotBlank(skillRow.attrCode)) {
					FightAttr skillAttr = new FightAttr(skillRow.attrCode);
					part.attr.add(skillAttr);
				}
				part.powerExt += skillRow.powerExt;
			}
		}
		return part;
	}

}
